﻿using Syspetro.Core.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Authentication;
using System.Text;
using System.Threading.Tasks;

namespace Syspetro.Core.HttpService
{
    public sealed class Http : Singleton<Http>
    {
        private readonly HttpClientHandler handler;

        private Http()
        {
            handler = new HttpClientHandler
            {
                UseDefaultCredentials = true,
                AutomaticDecompression = DecompressionMethods.GZip,
                SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12,
                ServerCertificateCustomValidationCallback = (sender, certificate, chain, errors) => { return true; }
            };
        }

        public (bool status, string response) Get(string address, string url, Action<HttpRequestHeaders> buildHeader = null)
        {
            try
            {
                var client = BuildClient(address, buildHeader);

                var response = client.GetAsync(url).Result;

                return response.IsSuccessStatusCode ? (true, response.Content.ReadAsStringAsync().Result) : (false, response.ReasonPhrase);
            }
            catch (Exception ex)
            {
                return (false, ex.Message);
            }
        }

        public (bool status, T data, string msg) Get<T>(string address, string url, Action<HttpRequestHeaders> buildHeader = null)
        {
            var (status, response) = Get(address, url, buildHeader);

            return status ? (true, response.ToObject<T>(), string.Empty) : (false, default, response);
        }

        public (bool status, string response) Post(string address, string url, object parameter, Action<HttpRequestHeaders> headers = null)
        {
            try
            {
                parameter ??= new object();

                var client = BuildClient(address);

                headers?.Invoke(client.DefaultRequestHeaders);

                var response = client.PostAsync(url, new StringContent(parameter.ToJson(), Encoding.UTF8, "application/json")).Result;

                if (response.IsSuccessStatusCode)
                    return (true, response.Content.ReadAsStringAsync().Result);

                return (false, response.ReasonPhrase);
            }
            catch (Exception ex)
            {
                return (false, ex.Message);
            }
        }

        public (bool status, T data, string msg) Post<T>(string address, string url, object parameter, Action<HttpRequestHeaders> headers = null)
        {
            parameter ??= new object();

            var client = BuildClient(address);

            headers?.Invoke(client.DefaultRequestHeaders);

            var response = client.PostAsync(url, new StringContent(parameter.ToJson(), Encoding.UTF8, "application/json")).Result;

            if (response.IsSuccessStatusCode)
                return (true, response.Content.ReadAsStringAsync().Result.ToObject<T>(), string.Empty);

            return (false, default(T), response.ReasonPhrase);
        }

        private HttpClient BuildClient(string address, Action<HttpRequestHeaders> buildHeader = null)
        {
            var client = new HttpClient(handler)
            {
                BaseAddress = new Uri(address)
            };

            if (buildHeader == null)
            {
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            }
            else
            {
                buildHeader(client.DefaultRequestHeaders);
            }

            return client;
        }
    }
}
